package com.guojing.jl.boot.admin.server.domain.values;

import lombok.ToString;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author: guojing
 * @create: 2023/8/11 12:07
 */
@lombok.Data
@ToString(exclude = "metadata")
public final class Registration implements Serializable {

    private final String name;

    @Nullable
    private final String managementUrl;

    private final String healthUrl;

    @Nullable
    private final String serviceUrl;

    private final String source;

    private final Map<String, String> metadata;

    @lombok.Builder(builderClassName = "Builder", toBuilder = true)
    private Registration(String name, @Nullable String managementUrl, String healthUrl, @Nullable String serviceUrl,
                         String source, @lombok.Singular("metadata") Map<String, String> metadata) {
        Assert.hasText(name, "'name' must not be empty.");
        Assert.hasText(healthUrl, "'healthUrl' must not be empty.");
        Assert.isTrue(checkUrl(healthUrl), "'healthUrl' is not valid: " + healthUrl);
        Assert.isTrue(!StringUtils.hasText(managementUrl) || checkUrl(managementUrl),
                "'managementUrl' is not valid: " + managementUrl);
        Assert.isTrue(!StringUtils.hasText(serviceUrl) || checkUrl(serviceUrl),
                "'serviceUrl' is not valid: " + serviceUrl);
        this.name = name;
        this.managementUrl = managementUrl;
        this.healthUrl = healthUrl;
        this.serviceUrl = serviceUrl;
        this.source = source;
        this.metadata = new LinkedHashMap<>();
        metadata.forEach(this.metadata::put);
    }

    public static Registration.Builder create(String name, String healthUrl) {
        return builder().name(name).healthUrl(healthUrl);
    }

    public static Registration.Builder copyOf(Registration registration) {
        return registration.toBuilder();
    }

    public Map<String, String> getMetadata() {
        return Collections.unmodifiableMap(this.metadata);
    }

    /**
     * Checks the syntax of the given URL.
     * @param url the URL.
     * @return true, if valid.
     */
    private boolean checkUrl(String url) {
        try {
            URI uri = new URI(url);
            return uri.isAbsolute();
        }
        catch (URISyntaxException ex) {
            return false;
        }
    }

    public static class Builder {

        // Will be generated by lombok

    }

}

